package stack

import "jvmgo/ch06/instructions/base"
import "jvmgo/ch06/rtda"

//复制操作数栈顶值
type DUP struct {
    base.NoOperandsInstruction
}

func (self *DUP) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    slot := stack.PopSlot()
    stack.PushSlot(slot)
    stack.PushSlot(slot)
}

// 复制栈顶值，插入栈顶以下两个值之后
// 操作前：栈底 value2 value1 ->
// 操作后：栈底 value1 value2 value1 ->
type DUP_X1 struct {
    base.NoOperandsInstruction
}

func (self *DUP_X1) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    slot1 := stack.PopSlot()
    slot2 := stack.PopSlot()
    stack.PushSlot(slot1)
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
}

// 复制栈顶值，插入栈顶以下2或者3个值之后,（value3 value2）可能组成一个值
// 操作前：栈底 value3 value2 value1 ->
// 操作后：栈底 value1 value3 value2 value1 ->
type DUP_X2 struct {
    base.NoOperandsInstruction
}

func (self *DUP_X2) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    slot1 := stack.PopSlot()
    slot2 := stack.PopSlot()
    slot3 := stack.PopSlot()
    stack.PushSlot(slot1)
    stack.PushSlot(slot3)
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
}

//复制操作数栈顶值（占两个位置long double）
type DUP2 struct {
    base.NoOperandsInstruction
}

func (self *DUP2) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    slot1 := stack.PopSlot()
    slot2 := stack.PopSlot()
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
}

type DUP2_X1 struct {
    base.NoOperandsInstruction
}

func (self *DUP2_X1) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    slot1 := stack.PopSlot()
    slot2 := stack.PopSlot()
    slot3 := stack.PopSlot()
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
    stack.PushSlot(slot3)
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
}

type DUP2_X2 struct {
    base.NoOperandsInstruction
}

func (self *DUP2_X2) Execute(frame *rtda.Frame) {
    stack := frame.OperandStack()
    slot1 := stack.PopSlot()
    slot2 := stack.PopSlot()
    slot3 := stack.PopSlot()
    slot4 := stack.PopSlot()
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
    stack.PushSlot(slot4)
    stack.PushSlot(slot3)
    stack.PushSlot(slot2)
    stack.PushSlot(slot1)
}
